package com.egg.auth.service.user.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.egg.auth.config.ReadConfig;
import com.egg.auth.entity.user.User;
import com.egg.auth.entity.user.UserAccount;
import com.egg.auth.enums.account.AccountStateEnum;
import com.egg.auth.enums.account.AccountTypeEnum;
import com.egg.auth.enums.user.UserStateEnum;
import com.egg.auth.mapper.user.UserAccountMapper;
import com.egg.auth.model.request.web.AccountOnPasswordPost;
import com.egg.auth.service.dept.IDeptLinkUserService;
import com.egg.auth.service.role.IRoleLinkUserService;
import com.egg.auth.service.user.IUserAccountService;
import com.egg.auth.service.user.IUserService;
import com.egg.auth.utils.PasswordUtil;
import com.egg.common.core.exception.CustomException;
import com.egg.common.mybatis.service.impl.BaseServiceImpl;
import com.egg.common.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
 * @author east
 */
@Slf4j
@Service
public class UserAccountServiceImpl extends BaseServiceImpl<UserAccountMapper, UserAccount> implements IUserAccountService {


    @Autowired
    private IUserService userService;
    @Autowired
    private IDeptLinkUserService deptLinkUserService;
    @Autowired
    private IRoleLinkUserService roleLinkUserService;


    @Transactional(rollbackFor = Throwable.class)
    @Override
    public Long addOnPassword(AccountOnPasswordPost param) {
        if (existByUsername(AccountTypeEnum.PASSWORD.getCode(), param.getUsername())) {
            throw new CustomException("用户名已存在");
        }
        User user = new User();
        user.setPhone(param.getPhone());
        user.setEmail(param.getEmail());
        user.setRealName(param.getRealName());
        user.setNickname(param.getNickname());
        user.setGender(param.getGender());
        user.setState(UserStateEnum.ENABLED.getCode());
        // 如果用户存在, 有可能通过其他方式注册, 这里绑定新的账号即可
        Optional<User> userOpt = userService.findByPhone(param.getPhone());
        userOpt.ifPresent(value -> user.setId(value.getId()));
        userService.baseSave(user);
        Long userId = user.getId();
        roleLinkUserService.put(userId, param.getRoleId());
        deptLinkUserService.put(userId, param.getDeptId());
        UserAccount userAccount = new UserAccount();
        if (ObjectUtil.isEmpty(param.getPassword())) {
            userAccount.setPassword(PasswordUtil.encryptionPassword(ReadConfig.userAccountDefaultPassword()));
        } else {
            userAccount.setPassword(PasswordUtil.encryptionPassword(param.getPassword()));
        }
        userAccount.setAccountType(AccountTypeEnum.PASSWORD.getCode());
        userAccount.setUsername(param.getUsername());
        userAccount.setState(AccountStateEnum.ENABLED.getCode());
        userAccount.setUserId(userId);
        baseSave(userAccount);
        return userId;
    }

    private boolean existByUsername(String accountType, String username) {
        if (ObjectUtil.isEmpty(accountType) || ObjectUtil.isEmpty(username)) {
            return true;
        }
        return findByUsername(accountType, username).isPresent();
    }

    @Override
    public Optional<UserAccount> findByUsername(String accountType, String username) {
        if (ObjectUtil.isEmpty(accountType)
                || ObjectUtil.isEmpty(username)
        ) {
            return Optional.empty();
        }
        LambdaQueryWrapper<UserAccount> qw = buildLambdaSortQw();
        qw.eq(UserAccount::getAccountType, accountType)
                .eq(UserAccount::getUsername, username);
        qw.last("LIMIT 1");
        return Optional.ofNullable(getOne(qw));
    }

    @Override
    public List<UserAccount> findByUserId(Serializable userId) {
        if (ObjectUtil.isEmpty(userId)) {
            return Collections.emptyList();
        }
        return findByUserId(Collections.singletonList(userId), Optional.empty());
    }

    @Override
    public Optional<UserAccount> findByUserId(Serializable userId, AccountTypeEnum accountType) {
        if (null == accountType) {
            return Optional.empty();
        }
        return findByUserId(Collections.singletonList(userId), Optional.of(accountType)).stream().findAny();
    }

    @Override
    public List<UserAccount> findByUserId(Collection<? extends Serializable> userId) {
        return findByUserId(userId, Optional.empty());
    }

    @Override
    public List<UserAccount> findByUserId(Collection<? extends Serializable> userId, Optional<AccountTypeEnum> accountType) {
        if (ObjectUtil.isEmpty(userId)) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<UserAccount> qw = buildLambdaSortQw();
        qw.in(UserAccount::getUserId, userId);
        accountType.ifPresent(o -> qw.eq(UserAccount::getAccountType, o.getCode()));
        return list(qw);
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void delByUserId(Serializable userId) {
        if (ObjectUtil.isEmpty(userId)) {
            return;
        }
        delByUserId(Collections.singletonList(userId));
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void delByUserId(Collection<? extends Serializable> userId) {
        if (ObjectUtil.isEmpty(userId)) {
            return;
        }
        LambdaQueryWrapper<UserAccount> qw = buildLambdaQw();
        qw.in(UserAccount::getUserId, userId);
        remove(qw);
    }


}
